# 回调模式：把函数作为参数，传递给另一个函数，延迟到另一个函数的某个时刻执行的过程叫回调。
# 缺点：回调地狱
# 面向过程的实现方式
def callback(*args, **kwargs):
    """回调函数"""
    # TODO 函数体的实现
    pass


def otherFunc(func. *args, **kwargs):
    """高阶函数，也叫包含函数"""
    # TODO 函数体的实现
    pass


# 面向对象的实现方式：策略模式
from abc import ABCMeta, abstractmethod


class Strategy(metaclass=ABCMeta):
    """算法的抽象类"""
    @abstractmethod
    def algorithm(self, *args, **kwargs):
        """定义算法"""
        pass


class StrategyA(Strategy):
    """策略A"""
    def algorithm(self, *args, **kwargs):
        print("算法A的实现")


class StrategyB(Strategy):
    """策略A"""
    def algorithm(self, *args, **kwargs):
        print("算法A的实现")


class Context:
    """上下文环境类"""
    def interface(self, strategy, *args, **kwargs):
        """交互接口"""
        print("回调执行前的操作")
        strategy.algorithm()
        print("回调执行后的操作")

# 调用方式
# context = Context()
# context.interface(StrategyA())
# context.interface(StrategyB())

# 回调在异步中的应用
# 异步的两种实现方式：多线程、多任务与事件循环

import requests
from threading import Thread

class DownloadThread(Thread):
    # 每次写文件的缓冲大小
    CHUNK_SIZE = 1024 * 512

    def __init__(self, fileName, url, savePath, callBackProgress, callBackFinished):
        super().__init__()
        self.__fileName = fileName
        self.__url = url
        self.__savePath = savePath
        self.__callBackProgress = callBackProgress
        self.__callBackFinished = callBackFinished

    def run(self):
        readSize = 0
        r = requests.get(url=self.__url, stream=True)
        totalSize = int(r.headers.get("Content-Length"))
        print("[下载%s] 文件大小:%d" % (self.__fileName, totalSize))
        with open(self.__savePath, "wb") as file:
            for chunk in r.iter_content(chunk_size=self.CHUNK_SIZE):
                if chunk:
                    file.write(chunk)
                    readSize += self.CHUNK_SIZE
                    self.__callBackProgress(self.__fileName, readSize, totalSize)
        self.__callBackFinished(self.__fileName)


def testDownload():
    def downloadProgress(fileName, readSize, totalSize):
        """"定义下载进度的回调函数"""
        percent = (readSize / totalSize) * 100
        print("[下载5s] 下载进度:%.2f%%" % (fileName, percent))

    def downloadFinished(filename):
        """定义下载完成后的回调函数"""
        print("[下载%s] 文件下载完成！" % fileName)

    
    print("开始下载TestForDownload1.pdf......")
    downloadUrl1 = ""
    download1 = DownloadThread("TestForDownload1", downloadUrl1, "./download.TestForDownload1.pdf", downloadProgress, downloadFinished)
    download1.start()
    print("开始下载TestForDownload2.pdf......")
    downloadUrl2 = ""
    download2 = DownloadThread("TestForDownload2", downloadUrl2, "./download.TestForDownload2.pdf", downloadProgress, downloadFinished)
    download2.start()

    # 执行其他任务
